package single.shop.common.lang.spring;

import java.util.Collection;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.Log4JLogger;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.Priority;

public class ShopLog extends Log4JLogger implements Log {
    private static final long serialVersionUID = 1L;
    String exitKeyWords = "weblog";

    private static final String FQCN = ShopLog.class.getName();

    private transient Logger logger = null;

    private String name = null;
    private static Priority traceLevel;

    public ShopLog() {
    }

    public ShopLog(String name) {
        this.name = name;
        this.logger = getLogger();
    }

    public ShopLog(Logger logger) {
        if (logger == null) {
            throw new IllegalArgumentException(
                    "Warning - null logger in constructor; possible log4j misconfiguration.");
        }

        this.name = logger.getName();
        this.logger = logger;
    }

    public void trace(Object message) {
        if (isTraceEnabled())
            getLogger().log(FQCN, traceLevel, getJsonMessage(message), null);
    }

    public void trace(Object message, Throwable t) {
        if (isTraceEnabled())
            getLogger().log(FQCN, traceLevel, getJsonMessage(message), t);
    }

    public void debug(Object message) {
        if (isDebugEnabled())
            getLogger().log(FQCN, Level.DEBUG, getJsonMessage(message), null);
    }

    public void debug(Object message, Throwable t) {
        if (isDebugEnabled())
            getLogger().log(FQCN, Level.DEBUG, getJsonMessage(message), t);
    }

    public void info(Object message) {
        if (isInfoEnabled())
            getLogger().log(FQCN, Level.INFO, getJsonMessage(message), null);
    }

    public void info(Object message, Throwable t) {
        if (isInfoEnabled())
            getLogger().log(FQCN, Level.INFO, getJsonMessage(message), t);
    }

    public void warn(Object message) {
        if (isWarnEnabled())
            getLogger().log(FQCN, Level.WARN, getJsonMessage(message), null);
    }

    public void warn(Object message, Throwable t) {
        if (isWarnEnabled())
            getLogger().log(FQCN, Level.WARN, getJsonMessage(message), t);
    }

    public void error(Object message) {
        if (isErrorEnabled())
            getLogger().log(FQCN, Level.ERROR, getJsonMessage(message), null);
    }

    public void error(Object message, Throwable t) {
        if (isErrorEnabled())
            getLogger().log(FQCN, Level.ERROR, getJsonMessage(message), t);
    }

    public void fatal(Object message) {
        if (isFatalEnabled())
            getLogger().log(FQCN, Level.FATAL, getJsonMessage(message), null);
    }

    public void fatal(Object message, Throwable t) {
        if (isFatalEnabled())
            getLogger().log(FQCN, Level.FATAL, getJsonMessage(message), t);
    }

    public Logger getLogger() {
        if (this.logger == null) {
            this.logger = Logger.getLogger(this.name);
        }
        return this.logger;
    }

    public boolean isDebugEnabled() {
        return getLogger().isDebugEnabled();
    }

    public boolean isErrorEnabled() {
        return getLogger().isEnabledFor(Level.ERROR);
    }

    public boolean isFatalEnabled() {
        return getLogger().isEnabledFor(Level.FATAL);
    }

    public boolean isInfoEnabled() {
        return getLogger().isInfoEnabled();
    }

    public boolean isTraceEnabled() {
        return getLogger().isEnabledFor(traceLevel);
    }

    public boolean isWarnEnabled() {
        return getLogger().isEnabledFor(Level.WARN);
    }

    private String getJsonMessage(Object message) {
        String messageString = "";
        if ((this.name != null)
                && (this.name.toLowerCase().indexOf(this.exitKeyWords) > -1)) {
            return message.toString();
        }
        if ((message instanceof Collection)) {
            messageString = formatListLog(message);
        } else if ((message instanceof String))
            messageString = "{message:" + message + "}";
        else {
            messageString = formatObjLog(message);
        }

        return messageString;
    }

    private static String formatObjLog(Object jsonObj) {
        String json = null;
        try {
            json = JSONObject.fromObject(jsonObj).toString();
        } catch (Exception e) {
            return jsonObj.toString();
        }
        return json;
    }

    public static String formatListLog(Object jsonObj) {
        String json = null;
        try {
            json = JSONArray.fromObject(jsonObj).toString();
        } catch (Exception e) {
            return jsonObj.toString();
        }

        return json;
    }

    static {
        if (!Priority.class.isAssignableFrom(Level.class)) {
            throw new InstantiationError("Log4J 1.2 not available");
        }

        try {
            traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(
                    null);
        } catch (Exception ex) {
            traceLevel = Priority.DEBUG;
        }
    }
}